From c702ebb63190cac143d6f5e94ff0b2904c24f1dd Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 28 Oct 2006 17:12:04 +0100 Subject: [PATCH] These are the proposed changes to XenD that adapt vTPM handling to the document and the implementation in the library. It's implementation is now similar to VIF and VBD. The implementation passes the first 2 tests in the vTPM- related tests in the xm-test suite. Minor conflict resolution by Ewan Mellor. Signed-off-by: Stefan Berger --- tools/python/xen/xend/XendAPI.py | 76 +++++++++++++++++++++---- tools/python/xen/xend/XendConfig.py | 20 ++++++- tools/python/xen/xend/XendDomainInfo.py | 18 ++++++ tools/python/xen/xend/XendError.py | 1 + tools/python/xen/xend/server/tpmif.py | 25 ++++++-- tools/python/xen/xm/create.py | 51 +++++++++-------- 6 files changed, 150 insertions(+), 41 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index f921b92e90..8cdb553d87 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -181,6 +181,28 @@ def valid_vdi(func): return check_vdi_ref +def valid_vtpm(func): + """Decorator to verify if vtpm_ref is valid before calling + method. + + @param func: function with params: (self, session, vtpm_ref) + @rtype: callable object + """ + def check_vtpm_ref(self, session, vtpm_ref, *args, **kwargs): + xendom = XendDomain.instance() + if type(vtpm_ref) == type(str()) and \ + xendom.is_valid_dev('vtpm', vtpm_ref): + return func(self, session, vtpm_ref, *args, **kwargs) + else: + return {'Status': 'Failure', + 'ErrorDescription': XEND_ERROR_VTPM_INVALID} + + # make sure we keep the 'api' attribute + if hasattr(func, 'api'): + check_vtpm_ref.api = func.api + + return check_vtpm_ref + def valid_sr(func): """Decorator to verify if sr_ref is valid before calling method. @@ -246,6 +268,7 @@ class XendAPI: 'VBD': (valid_vbd, session_required), 'VIF': (valid_vif, session_required), 'VDI': (valid_vdi, session_required), + 'VTPM':(valid_vtpm, session_required), 'SR': (valid_sr, session_required)} # Cheat methods @@ -580,8 +603,6 @@ class XendAPI: 'actions_after_reboot', 'actions_after_suspend', 'actions_after_crash', - 'TPM_instance', - 'TPM_backend', 'bios_boot', 'platform_std_VGA', 'platform_serial', @@ -645,14 +666,6 @@ class XendAPI: dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_vtpms()) - def vm_get_tpm_instance(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() # unsupported by xc - - def vm_get_tpm_backend(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() # unsupported by xc - def vm_get_pci_bus(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() # unsupported by xc @@ -1262,6 +1275,49 @@ class XendAPI: return xen_api_error(XEND_ERROR_VDI_INVALID) + # Xen API: Class VTPM + # ---------------------------------------------------------------- + + VTPM_attr_ro = [ ] + VTPM_attr_rw = ['type', + 'VM', + 'backend', + 'instance'] + + VTPM_attr_inst = VTPM_attr_rw + + # object methods + def vtpm_get_record(self, session, vtpm_ref): + xendom = XendDomain.instance() + vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref) + if not vm: + return xen_api_error(XEND_ERROR_VTPM_INVALID) + cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref) + if not cfg: + return xen_api_error(XEND_ERROR_VTPM_INVALID) + valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \ + self.Base_attr_ro + self.Base_attr_rw + for k in cfg.keys(): + if k not in valid_vtpm_keys: + del cfg[k] + + return xen_api_success(cfg) + + # class methods + def vtpm_create(self, session, vtpm_struct): + xendom = XendDomain.instance() + if xendom.is_valid_vm(vtpm_struct['VM']): + dom = xendom.get_vm_by_uuid(vtpm_struct['VM']) + try: + vtpm_ref = dom.create_vtpm(vtpm_struct) + xendom.managed_config_save(dom) + return xen_api_success(vtpm_ref) + except XendError: + return xen_api_error(XEND_ERROR_TODO) + else: + return xen_api_error(XEND_ERROR_DOMAIN_INVALID) + + # Xen API: Class SR # ---------------------------------------------------------------- SR_attr_ro = ['VDIs', diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 7bed6d676c..0787ebd79f 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -110,8 +110,6 @@ XENAPI_UNSUPPORTED_IN_LEGACY_CFG = [ 'vcpus_features_force_on', 'vcpus_features_force_off', 'actions_after_suspend', - 'tpm_instance', - 'tpm_backends', 'bios_boot', 'platform_std_vga', 'platform_serial', @@ -570,11 +568,14 @@ class XendConfig(dict): # ------------------ cfg['vif_refs'] = [] cfg['vbd_refs'] = [] + cfg['vtpm_refs'] = [] for dev_uuid, (dev_type, dev_info) in cfg['device'].items(): if dev_type == 'vif': cfg['vif_refs'].append(dev_uuid) elif dev_type in ('vbd','tap'): cfg['vbd_refs'].append(dev_uuid) + elif dev_type == 'vtpm': + cfg['vtpm_refs'].append(dev_uuid) return cfg @@ -610,6 +611,8 @@ class XendConfig(dict): cfg['vif_refs'] = [] if 'vbd_refs' not in cfg: cfg['vbd_refs'] = [] + if 'vtpm_refs' not in cfg: + cfg['vtpm_refs'] = [] return cfg @@ -747,6 +750,8 @@ class XendConfig(dict): self['vif_refs'] = [] if 'vbd_refs' not in self: self['vbd_refs'] = [] + if 'vtpm_refs' not in self: + self['vtpm_refs'] = [] def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None): if dev_type not in XendDevices.valid_devices(): @@ -815,7 +820,16 @@ class XendConfig(dict): self['device'][dev_uuid] = (dev_type, dev_info) self['vbd_refs'].append(dev_uuid) return dev_uuid - + + elif dev_type == 'vtpm': + if cfg_xenapi.get('type'): + dev_info['type'] = cfg_xenapi.get('type') + dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) + dev_info['uuid'] = dev_uuid + self['device'][dev_uuid] = (dev_type, dev_info) + self['vtpm_refs'].append(dev_uuid) + return dev_uuid + elif dev_type == 'tap': dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image') dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device') diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 721edad303..46d4c78e22 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1897,6 +1897,24 @@ class XendDomainInfo: return dev_uuid + def create_vtpm(self, xenapi_vtpm): + """Create a VTPM device from the passed struct in Xen API format. + + @return: uuid of the device + @rtype: string + """ + + dev_uuid = self.info.device_add('vtpm', cfg_xenapi = xenapi_vtpm) + if not dev_uuid: + raise XendError('Failed to create device') + + if self.state in (DOM_STATE_HALTED,): + sxpr = self.info.device_sxpr(dev_uuid) + devid = self.getDeviceController('vtpm').createDevice(sxpr) + raise XendError("Device creation failed") + + return dev_uuid + def has_device(self, dev_class, dev_uuid): return (dev_uuid in self.info['%s_refs' % dev_class]) diff --git a/tools/python/xen/xend/XendError.py b/tools/python/xen/xend/XendError.py index e7e274ff1c..5947145267 100644 --- a/tools/python/xen/xend/XendError.py +++ b/tools/python/xen/xend/XendError.py @@ -47,6 +47,7 @@ XEND_ERROR_UNSUPPORTED = ('EUNSUPPORTED', 'Method Unsupported') XEND_ERROR_VM_INVALID = ('EVMINVALID', 'VM Invalid') XEND_ERROR_VBD_INVALID = ('EVBDINVALID', 'VBD Invalid') XEND_ERROR_VIF_INVALID = ('EVIFINVALID', 'VIF Invalid') +XEND_ERROR_VTPM_INVALID = ('EVTPMINVALID', 'VTPM Invalid') XEND_ERROR_VDI_INVALID = ('EVDIINVALID', 'VDI Invalid') XEND_ERROR_SR_INVALID = ('ESRINVALID', 'SR Invalid') XEND_ERROR_TODO = ('ETODO', 'Lazy Programmer Error') diff --git a/tools/python/xen/xend/server/tpmif.py b/tools/python/xen/xend/server/tpmif.py index 6f6ab93b1a..c313efe2a8 100644 --- a/tools/python/xen/xend/server/tpmif.py +++ b/tools/python/xen/xend/server/tpmif.py @@ -49,22 +49,37 @@ class TPMifController(DevController): if inst == -1: inst = int(sxp.child_value(config, 'instance' , '0')) + typ = sxp.child_value(config, 'type') + uuid = sxp.child_value(config, 'uuid') + log.info("The domain has a TPM with pref. instance %d and devid %d.", inst, devid) back = { 'pref_instance' : "%i" % inst, 'resume' : "%s" % (self.vm.getResume()) } + if typ: + back['type'] = typ + if uuid: + back['uuid'] = uuid + front = { 'handle' : "%i" % devid } return (devid, back, front) - def configuration(self, devid): - - result = DevController.configuration(self, devid) + def getDeviceConfiguration(self, devid): + """Returns the configuration of a device""" + result = DevController.getDeviceConfiguration(self, devid) - instance = self.readBackend(devid, 'instance') + (instance, uuid, type) = \ + self.readBackend(devid, 'instance', + 'uuid', + 'type') if instance: - result.append(['instance', instance]) + result['instance'] = instance + if uuid: + result['uuid'] = uuid + if type: + result['type'] == type return result diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 7b43ee79da..aab0d930ec 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -291,7 +291,7 @@ gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT,ba This option may be repeated to add more than one vif. Specifying vifs will increase the number of interfaces as needed.""") -gopts.var('vtpm', val="instance=INSTANCE,backend=DOM", +gopts.var('vtpm', val="instance=INSTANCE,backend=DOM,type=TYPE", fn=append_value, default=[], use="""Add a TPM interface. On the backend side use the given instance as virtual TPM instance. The given number is merely the @@ -299,7 +299,11 @@ gopts.var('vtpm', val="instance=INSTANCE,backend=DOM", which instance number will actually be assigned to the domain. The associtation between virtual machine and the TPM instance number can be found in /etc/xen/vtpm.db. Use the backend in the - given domain.""") + given domain. + The type parameter can be used to select a specific driver type + that the VM can use. To prevent a fully virtualized domain (HVM) + from being able to access an emulated device model, you may specify + 'paravirtualized' here.""") gopts.var('access_control', val="policy=POLICY,label=LABEL", fn=append_value, default=[], @@ -585,27 +589,28 @@ def configure_vtpm(config_devs, vals): """Create the config for virtual TPM interfaces. """ vtpm = vals.vtpm - vtpm_n = 1 - for idx in range(0, vtpm_n): - if idx < len(vtpm): - d = vtpm[idx] - instance = d.get('instance') - if instance == "VTPMD": - instance = "0" - else: - if instance != None: - try: - if int(instance) == 0: - err('VM config error: vTPM instance must not be 0.') - except ValueError: - err('Vm config error: could not parse instance number.') - backend = d.get('backend') - config_vtpm = ['vtpm'] - if instance: - config_vtpm.append(['pref_instance', instance]) - if backend: - config_vtpm.append(['backend', backend]) - config_devs.append(['device', config_vtpm]) + if len(vtpm) > 0: + d = vtpm[0] + instance = d.get('instance') + if instance == "VTPMD": + instance = "0" + else: + if instance != None: + try: + if int(instance) == 0: + err('VM config error: vTPM instance must not be 0.') + except ValueError: + err('Vm config error: could not parse instance number.') + backend = d.get('backend') + typ = d.get('type') + config_vtpm = ['vtpm'] + if instance: + config_vtpm.append(['pref_instance', instance]) + if backend: + config_vtpm.append(['backend', backend]) + if typ: + config_vtpm.append(['type', type]) + config_devs.append(['device', config_vtpm]) def configure_vifs(config_devs, vals): -- 2.30.2